﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;
using System.IO;

namespace KeelKit.KeelKit_CodeLineCounter
{
   public  class FilesICO
    {

        public class Shell32
        {

            public const int MAX_PATH = 256;
            [StructLayout(LayoutKind.Sequential)]
            public struct SHFILEINFO
            {
                public const int NAMESIZE = 80;
                public IntPtr hIcon;
                public int iIcon;
                public uint dwAttributes;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
                public string szDisplayName;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NAMESIZE)]
                public string szTypeName;
            };
            public const uint SHGFI_ICON = 0x000000100;     // get icon 
            public const uint SHGFI_LINKOVERLAY = 0x000008000;     // put a 	link overlay on icon 
            public const uint SHGFI_LARGEICON = 0x000000000;     // get large icon 
            public const uint SHGFI_SMALLICON = 0x000000001;     // get small icon 
            public const uint SHGFI_OPENICON = 0x000000002;     // get open icon 
            public const uint SHGFI_USEFILEATTRIBUTES = 0x000000010;     // use passed dwFileAttribute 
            // 
            public const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
            public const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
            [DllImport("Shell32.dll")]
            public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
        }
        public class User32
        {
            ///  
            /// Provides access to function required to delete handle. This method is used internally 
            /// and is not required to be called separately. 
            ///  
            /// Pointer to icon handle. 
            /// N/A 
            [DllImport("User32.dll")]
            public static extern int DestroyIcon(IntPtr hIcon);
        }

        public enum IconSize
        {
            ///  
            /// Specify large icon - 32 pixels by 32 pixels. 
            ///  
            Large = 0,
            ///  
            /// Specify small icon - 16 pixels by 16 pixels. 
            ///  
            Small = 1


        }
        
        ///  
        /// Options to specify whether folders should be in the open or closed state. 
        ///  
        public enum FolderType
        {
            ///  
            /// Specify open folder. 
            ///  
            Open = 0,
            ///  
            /// Specify closed folder. 
            ///  
            Closed = 1
        }
    
       
        public static System.Drawing.Icon GetFileIcon(string name, IconSize size, bool linkOverlay )
        {
            Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
            uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_USEFILEATTRIBUTES;
            if (true == linkOverlay) flags += Shell32.SHGFI_LINKOVERLAY;
            /* Check the size specified for return. */
            if (IconSize.Small == size)
            {
                flags += Shell32.SHGFI_SMALLICON;
            }
            else
            {
                flags += Shell32.SHGFI_LARGEICON;
            }
 
            Shell32.SHGetFileInfo(name, Shell32.FILE_ATTRIBUTE_NORMAL, ref shfi, (uint)System.Runtime.InteropServices.Marshal.SizeOf(shfi), flags);
            // Copy (clone) the returned icon to a new object, thus allowing us to 	clean-up properly 
            System.Drawing.Icon icon = (System.Drawing.Icon)System.Drawing.Icon.FromHandle(shfi.hIcon).Clone();
            User32.DestroyIcon(shfi.hIcon);  // Cleanup 
            //Bitmap bmp = icon.ToBitmap();
            //bmp.MakeTransparent(Color.Black);
            ////bmp.MakeTransparent(Color.White );
            //icon = Icon.FromHandle(bmp.GetHicon());
            return icon;
        }
        [DllImport("shell32.dll", EntryPoint = "ExtractAssociatedIcon", CharSet = CharSet.Auto)]
        public static extern IntPtr IntExtractAssociatedIcon(HandleRef hInst, StringBuilder iconPath, ref int index);

        public static IntPtr ExtractAssociatedIcon(HandleRef hInst, StringBuilder iconPath, ref int index)
        {
            return IntExtractAssociatedIcon(hInst, iconPath, ref index);
        }
      static  HandleRef NullHandleRef=new HandleRef();
        private static Icon ExtractAssociatedIcon(string filePath, int index)
        {
       
                StringBuilder iconPath = new StringBuilder(260);
                iconPath.Append(filePath);
                IntPtr handle =  ExtractAssociatedIcon(NullHandleRef, iconPath, ref index);
                if (handle != IntPtr.Zero)
                {
                   // IntSecurity.ObjectFromWin32Handle.Demand();
                    Icon icon = Icon.FromHandle(handle).Clone() as Icon ; ;
                    User32.DestroyIcon(handle);
                    return icon;
                }
 
            return null;
        }


        public static System.Drawing.Icon GetFolderIcon(string path ,IconSize size, FolderType folderType)
        {
            // Need to add size check, although errors generated at present! 
            uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_USEFILEATTRIBUTES;
            if (FolderType.Open == folderType)
            {
                flags += Shell32.SHGFI_OPENICON;
            }

            if (IconSize.Small == size)
            {
                flags += Shell32.SHGFI_SMALLICON;
            }
            else
            {
                flags += Shell32.SHGFI_LARGEICON;
            }
            // Get the folder icon 
            Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
            Shell32.SHGetFileInfo(path, Shell32.FILE_ATTRIBUTE_DIRECTORY, ref shfi, (uint)System.Runtime.InteropServices.Marshal.SizeOf(shfi), flags);
            System.Drawing.Icon.FromHandle(shfi.hIcon); // Load the icon from an HICON handle 
            // Now clone the icon, so that it can be successfully stored in an ImageList 
            System.Drawing.Icon icon = (System.Drawing.Icon)System.Drawing.Icon.FromHandle(shfi.hIcon).Clone();
            User32.DestroyIcon(shfi.hIcon);  // Cleanup 
            Bitmap bmp = icon.ToBitmap();
            bmp.MakeTransparent(Color.Black);
            //bmp.MakeTransparent(Color.White );
            icon = Icon.FromHandle(bmp.GetHicon());
            return icon;
        }
        public static string GetFileICOKey(string filename,TreeView tv)
        {

            System.IO.FileInfo fi = new System.IO.FileInfo(filename);
            string result = fi.Extension + "T";
            if ( fi.Extension !="" )
            {
                if (!tv.ImageList.Images.ContainsKey(fi.Extension))
                {

                    tv.ImageList.Images.Add(fi.Extension, GetFileIcon(filename, IconSize.Large, true));//,ExtractAssociatedIcon(filename ,1)); 
                    tv.ImageList.Images.Add(fi.Extension + "T",  GetFileIcon(filename, IconSize.Large, false));//ExtractAssociatedIcon(filename,2));//
                }
            }
            else if (fi.Directory.Exists)
            {
                if (!tv.ImageList.Images.ContainsKey(filename))
                {
                    tv.ImageList.Images.Add(filename, GetFolderIcon(filename, IconSize.Large, FolderType.Open));
                    tv.ImageList.Images.Add(filename + "T", GetFolderIcon(filename, IconSize.Large, FolderType.Closed));
                }
                result =filename + "T";
            }
            return result ;
        }


    }
}
